// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "ParamDim.hpp"
#include "Exception.hpp"

using namespace ninf::lib;
using namespace ninf::gen;
ParamDim :: ParamDim(DataInputStream & dis) // throws Exception
  : 
size(dis), start(dis), end(dis), step(dis){}

ParamDim :: ParamDim(Expression size, Expression start, 
			 Expression end,  Expression step)
  :
size(size), start(start), end(end), step(step){}

ParamDim :: ParamDim(Expression * size, Expression * start, 
			 Expression * end,  Expression * step)
  :
size(*size), start(*start), end(*end), step(*step){}

void 
ParamDim :: writeTo(DataOutputStream & dos){
  EBEGIN { size .writeTo(dos); } EEND
  EBEGIN { start.writeTo(dos); } EEND
  EBEGIN { end  .writeTo(dos); } EEND
  EBEGIN { step .writeTo(dos); } EEND
}

#define PUTTAB(fp,tab)   { for (int i = 0; i < tab; i++) fprintf(fp, "\t");}


/* write out declaration string */
void
ParamDim :: writeDeclaration(int tab, int index0, int index1, int index2, FILE * fp){
  size. writeDeclaration(tab, "size",  index0, index1, index2, fp);
  start.writeDeclaration(tab, "start", index0, index1, index2, fp);
  end.  writeDeclaration(tab, "end",   index0, index1, index2, fp);
  step. writeDeclaration(tab, "step",  index0, index1, index2, fp);

  PUTTAB(fp, tab);
  fprintf(fp, 
	  "ParamDim dim_%d_%d_%d(size_%d_%d_%d, start_%d_%d_%d, end_%d_%d_%d, step_%d_%d_%d);",
	  index0, index1, index2,
	  index0, index1, index2,
	  index0, index1, index2,
	  index0, index1, index2,
	  index0, index1, index2);
  fprintf(fp, "\n");
}

ArgDim * 
ParamDim :: calc(int * iArgs, int len){
  int iSize  = size. evaluate(iArgs, len, 1);
  int iStart = start.evaluate(iArgs, len, 0);
  int iEnd   = end.  evaluate(iArgs, len, iSize);
  int iStep  = step. evaluate(iArgs, len, 1);

  return new ArgDim(iSize, iStart, iEnd, iStep);
}
